package uy.com.dino.samefile.service.impl;

import uy.com.dino.samefile.dao.ReviewDao;
import uy.com.dino.samefile.loader.Loader;
import uy.com.dino.samefile.model.FileInfo;
import uy.com.dino.samefile.model.Review;
import uy.com.dino.samefile.service.ReviewService;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class ReviewServiceImpl implements ReviewService {

    private ReviewDao reviewDao;

    private Loader loader;

    public void setReviewDao(ReviewDao reviewDao) {
        this.reviewDao = reviewDao;
    }

    public void setLoader(Loader loader) {
        this.loader = loader;
    }

    @Override
    public void saveReview(Review review) {
        reviewDao.insert(review);
    }

    @Override
    public Review executeReview(String name, String path) {
        Review review = new Review();
        review.setName(name);

        List<FileInfo> fileInfoList = this.loader.loadFileInfo(path);
        review.setFileInfoList(fileInfoList);

        return review;
    }

    @Override
    public void compareReviews(String name1, String name2) {
        System.out.println("comparing " + name1 + " " + name2 + "...");

        Review review1 = this.reviewDao.getReviewByName(name1);
        Review review2 = this.reviewDao.getReviewByName(name2);

        this.compareReviews(review1, review2);
    }

    public void compareReviews(Review review1, Review review2) {
        Map<String, String> founds = new HashMap<String, String>();

        List<FileInfo> fileInfoList1 = review1.getFileInfoList();
        List<FileInfo> fileInfoList2 = review2.getFileInfoList();

        System.out.println("Unicos en " + review1.getName());
        for (FileInfo fileInfo1 : fileInfoList1) {
            boolean found = false;
            for (int i = 0; i < fileInfoList2.size() && !found; i++) {
                FileInfo fileInfo2 = fileInfoList2.get(i);
                if (fileInfo1.equals(fileInfo2)) {
                    found = true;
                    founds.put(fileInfo2.getHashCode(), fileInfo2.getPath());
                }
            }
            if (!found) {
                System.out.println(review1.getName() + "-" + fileInfo1);
            }
        }

        System.out.println("====================================================================");
        System.out.println("Unicos en " + review2.getName());
        for (FileInfo fileInfo : fileInfoList2) {
            if (!founds.containsKey(fileInfo.getHashCode())) {
                System.out.println(review2.getName() + "-" + fileInfo);
            }
        }
        System.out.println("====================================================================");

    }

    @Override
    public void repitedInReview(Review review) {
        System.out.println("calculating repiter for " + review.getName());
        Map<String, String> founds = new HashMap<String, String>();
        Map<String, StringBuffer> doubles = new HashMap<String, StringBuffer>();
        System.out.println("Repetidos en " + review.getName());

        List<FileInfo> fileInfoList = review.getFileInfoList();
        for (FileInfo fileInfo : fileInfoList) {
            if (!founds.containsKey(fileInfo.getHashCode())) {
                founds.put(fileInfo.getHashCode(), fileInfo.getPath());
            } else {
                StringBuffer sb = null;
                if (!doubles.containsKey(fileInfo.getHashCode())) {
                    String path = founds.get(fileInfo.getHashCode());
                    sb = new StringBuffer(path);
                    doubles.put(fileInfo.getHashCode(), sb);
                } else {
                    sb = doubles.get(fileInfo.getHashCode());
                }
                sb.append(", ");
                sb.append(fileInfo.getPath());
            }
        }

        Set<String> keys = doubles.keySet();
        for (String key : keys) {
            StringBuffer sb = doubles.get(key);
            System.out.println(key + " " + sb.toString());
        }
        System.out.println("====================================================================");

    }

    @Override
    public void exportReview(Review review, String fileName) {
        System.out.println("exporting " + fileName);
        try {
            JAXBContext contextObj = JAXBContext.newInstance(Review.class);

            Marshaller marshallerObj = contextObj.createMarshaller();
            marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

            marshallerObj.marshal(review, new FileOutputStream(fileName));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public Review importReview(String fileName) {
        Review review = null;
        System.out.println("importing " + fileName);
        try {
            JAXBContext contextObj = JAXBContext.newInstance(Review.class);

            Unmarshaller unmarshaller = contextObj.createUnmarshaller();
            review = (Review) unmarshaller.unmarshal(new File(fileName));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return review;
    }
}
